home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / DevCon / Orlando_1993 / Devcon93.4 / Notes / Amiga_Debugging next >
Encoding:
Text File  |  1992-12-22  |  44.2 KB  |  969 lines

  1.  
  2.                            Using Amiga Debugging Tools
  3.                            ===========================
  4.  
  5.         Carolyn Scheppner, Technical Manager, CATS U.S.
  6.         Adam Levin-Delson, CATS Amiga Support Engineer
  7.  
  8.  
  9. Have you ever experienced any of the following problems with software ?
  10.  
  11. The software runs well on your system but some others report it
  12.    has problems on their systems.
  13. The software runs well by itself but has problems running with
  14.    or after other software.
  15. The software runs well most of the time but occasionally crashes
  16.    or fails for no apparent reason.
  17.  
  18. You can find and eliminate many of these types of hidden software problems
  19. by running Amiga debugging and stressing tools while developing and
  20. testing your product.
  21. Hidden and obvious software problems are often caused by use of null
  22. pointers, uninitialized pointers, improperly initialized structures,
  23. improper use of IO requests, improper abort code, improper memory usage,
  24. or overwriting of memory allocations.
  25. By using Enforcer, Mungwall, IO_Torture, Scratch, Memoration, and other
  26. Amiga debugging and testing tools, you can catch most of these problems
  27. before you ship a product.
  28. In fact, many companies now require that all of their inhouse
  29. software pass at least Enforcer and Mungwall testing, and have also added
  30. this requirement to their contracts for outside development.
  31. Many other CATS tools such as Devmon, Owner, and LVO can help to pinpoint
  32. the causes of problems.  You have these tools.  Here are hints on how to
  33. use them, when to use them, and how to get the most from their output.
  34.  
  35.  
  36. Enforcer and Mungwall
  37. =====================
  38.  
  39. Enforcer and Mungwall are the top two bug finding and bug prevention tools.
  40. Enforcer is an MMU-based debugging tool by Michael Sinz,
  41. based on an earlier tool by Bryce Nesbitt.  An MMU is a memory management
  42. unit which can be configured to trap accesses to specified ranges of memory.
  43. The 68030 and 68040 processors have a built-in MMU, and most 68020
  44. boards contain a separate MMU.  Because it is MMU-based, Enforcer can trap
  45. reads and writes of low memory and non-existent memory the
  46. instant these accesses (also known as "Enforcer hits") occur.
  47. This allows you to catch usage of null pointers and some uninitialized
  48. pointers in your program, and even accesses which would have trashed
  49. low memory or otherwise crashed the system.
  50. Some of these accesses may seem harmless
  51. on your system (such as reads of address 0) but could cause your program
  52. to fail in the field.  If you are developing commercial software
  53. (or any software that you plan to distribute) it is extremely
  54. important that you invest in a MMU, or at the very least make sure
  55. that your software is tested on machines with an MMU, Enforcer,
  56. and Mungwall.  As more of the development community begins running
  57. these tools, software that is unusable in their presence will
  58. simply not be used.  The main differences between the
  59. new Enforcer and the previous Enforcers is that the new Enforcer
  60. also works with 68040 processors and has a wide variety of output
  61. options built in.  In addition, due to the variety of output options,
  62. the new Enforcer must be RUN.  The new Enforcer requires at least V37 OS,  
  63. so if you need to run Enforcer on a 1.3 machine, you must use the
  64. older Enforcer 2.8b which we will probably be renaming "Enforcer1.3".
  65. Full docs are provided with Enforcer.
  66.  
  67.  
  68. Enforcer is even more powerful when used in combination with Mungwall.
  69. Mungwall is a combination memory munging tool by Ewout Walraven which
  70. is based on Memmung by Bryce Nesbitt and Memwall by Randell Jesup.
  71. The "mung" part of Mungwall fills all of free memory (and all
  72. subsequently freed memory) with a nasty odd 32-bit values like
  73. $DEADF00D.  Such a values are almost guaranteed to cause serious
  74. problems for any program that uses uninitialized pointers or
  75. structures, or uses memory or allocations after they are freed.
  76. Such usages can occur, for example, when allocations are not
  77. freed in the correct order.
  78.  
  79. Mungwall uses a few different nasty 32-bit values in its memory
  80. munging to help you diagnose any problems.
  81.  
  82.  - Except when Enforcer is running, location 0 is set to $C0DEDBAD
  83.    so that programs referencing location zero will not find a value.
  84.    Programs referencing location 0 as a string will get a string of
  85.    high ASCII characters rather than a null string, and programs
  86.    using null structure pointers should be irritated into crashing.
  87.    When Enforcer is running, this is not necessary because with location
  88.    0 containing 0, Enforcer can trap these low memory accesses by itself.
  89.  
  90.  - On startup all free memory is munged with $ABADCAFE. If this number
  91.    shows up, someone is referencing memory in the free list.
  92.  
  93.  - Except when MEMF_CLEAR is set, memory is pre-munged on allocation with
  94.    $DEADFOOD. When this is seen in an Enforcer report, the caller is
  95.    allocating memory and doesn't initialize it before using it.
  96.  
  97.  - Memory is filled with $DEADBEEF when it is deallocated, encouraging
  98.    programs reusing freed memory to crash or get Enforcer hits.
  99.  
  100.  
  101. The "wall" part of Mungwall allocates
  102. extra memory before and after every memory allocation and
  103. fills this "wall" with a fill pattern and other information.
  104. On each de-allocation, Mungwall checks to make sure that the
  105. deallocation size matches the size of the allocation, and checks
  106. to make sure that the walls have not been overwritten.  Mungwall
  107. also watches for 0-size allocations, 0-size deallocations, and
  108. 0-address deallocations.
  109. Mungwall checks for incorrect allocations (such as 0 size)
  110. during AllocMem, and checks for incorrect deallocations or trashing
  111. around allocations during FreeMem.  If trashing or incorrect deallocation
  112. is detected, Mungwall will both report it and refuse to free the memory.
  113. These reports are all known as "Mungwall hits".
  114.  
  115. The latest Mungwall can also optionally report on failed allocations
  116. with the SHOWFAIL option.  In addition, Mungwall has an option
  117. to "snoop" and report on all memory allocations and deallocations
  118. for all tasks or specified tasks.  This can be useful when tracking
  119. down memory losses.  The sometimes voluminous snoop output can be run through
  120. the snoopstrip program which will throw away all matching
  121. allocation/deallocation pairs.
  122.  
  123. Another useful recently added Mungwall feature is the NAMETAG option.
  124. When this option is active, Mungwall will tag all memory allocations with
  125. the first 16 characters of the name of the task, process, or command
  126. that allocated the memory.  A program called Munglist can then
  127. do its best to show the names of the allocators of currently allocated pieces
  128. of memory.  This can be very useful in tracking down memory losses.
  129. However, keep in mind that some of an application's allocations
  130. may be done by a different system task (for example, if an application
  131. opens a file, a file handle or buffers may be allocated by the process
  132. for the disk volume).
  133.  
  134. Mungwall may be used without Enforcer and on non-MMU machines.
  135. If you don't have an MMU, at least test with Mungwall alone.
  136. If you are using uninitialized memory or memory after it is freed,
  137. Mungwall should help to crash you immediately (as you might
  138. crash on a user's machine when he runs other programs at the
  139. same time as yours).  Mungwall is more pleasant when used with
  140. Enforcer however, since it will generally incite an Enforcer hit
  141. when memory is misused, rather than a crash.
  142.  
  143. It is generally not safe or recommended to turn Mungwall off and
  144. back on without rebooting.  This is because Mungwall recognizes
  145. its walled allocations by looking for a special value it has placed
  146. near the beginning of the allocation.  If a program allocates memory while
  147. Mungwall is running, then frees it while Mungwall is turned off,
  148. and another program reallocates the some of the same memory while Mungwall
  149. is turned off, and then tries to deallocate it with Mungwall turned
  150. back on, Mungwall may generate Mungwall hits due to incorrect data.
  151. Note that this can also occasionally happen on a soft-reboot if a task
  152. that starts up and allocates memory before Mungwall is run happens to
  153. receive a Mungwall-tagged piece of memory that was in use before reboot,
  154. and then frees the memory after Mungwall is running.  To identify
  155. such problems, turn your machine off for 15 seconds or so to clear
  156. memory, turn it back on, and retest.
  157.  
  158. A useful alternative to turning Mungwall off and on is the Mungwall
  159. UPDATE feature.  UPDATE allows you to turn on and off many of the
  160. options of another running copy of Mungwall.  For example, you
  161. could turn off the MEGASTACK option via Mungwall UPDATE NOMEGASTACK
  162. or turn on the SHOWFAIL option with Mungwall UPDATE SHOWFAIL.
  163.  
  164. Debugging Terminals
  165. ===================
  166.  
  167. Enforcer and Mungwall both output their debugging information
  168. to the serial port at the baud rate your machine's serial
  169. hardware is set to.  At powerup, your serial hardware is set
  170. to 9600 baud, but you can modify this by bringing up a terminal
  171. package and setting a baud rate.  The optimal debugging setup
  172. is to connect your Amiga via a null modem serial cable to another
  173. Amiga or computer running a terminal package with ACSII capture
  174. capability.  Both Enforcer and Mungwall include CTRL-G's in their output
  175. to generate a beep with most terminal packages, and the ASCII capture
  176. capability will allow you to capture all serial debugging
  177. output to a file for examination.  This is especially useful when
  178. combined with serial kprintf() (debug.lib) debugging statements in
  179. your code such as kprintf("About to close window $%lx\n",win).
  180.  
  181. But some developers don't have a second machine to use as a debugging
  182. terminal, or may need to debug a serial application which would
  183. interfere with serial debugging output.
  184. So two other options exist.  One is to use the parallel
  185. versions of the debugging tools, and the parallel debugging "dprintf"
  186. command (from ddebug.lib) and connect a parallel printer for
  187. the output.  The benefit of serial and parallel debugging is that
  188. you can get some information out and capture it even if your
  189. machine is crashing, and even if your application has taken
  190. over the system.  The other option is "Sushi".
  191.  
  192.  
  193. Sushi
  194. =====
  195.  
  196. For most applications, an option now exists for debugging
  197. on a single machine.  It's called "Sushi" (a late-night name loosely
  198. based on the fact that it captures "raw" serial output).
  199. Sushi captures all raw serial debugging output (such as kprintf,
  200. new Enforcer with RAWIO option, Mungwall, IO_Torture, etc.)
  201. and has its AmigaDOS process send the debug information to stdout.
  202. This means you can redirect Sushi's output to a an AUTO/CON window
  203. (and the window will pop open if you have any hits), or to a multiserial
  204. port, etc.  Sushi can also be told to save its circular buffer
  205. (via CTRL-F signal or via a separate SUSHI SAVEAS FILENAME command),
  206. or to empty its buffer (CTRL-E signal or a separate SUSHI EMPTY command).
  207.  
  208. Sushi also can operate in quiet mode, just capturing debugging output,
  209. and provides a program task signalling interface which allows an external
  210. application to be written to display the captured debugging output
  211. (for those of you who want a fancier debugging display program).
  212. A benefit of Sushi is that fairly voluminous debugging output
  213. can be used even from within interrupt code or intense task code
  214. because Sushi only has to place the text bytes in a ram buffer,
  215. and the actual output is done by a separate process.
  216. See Sushi.doc for more information and a source for a sample
  217. external display program.
  218.  
  219. Sample user-startup:
  220.  
  221. run >NIL: Mungwall
  222. run >NIL: Enforcer RAWIO
  223. run >NIL: sushi <>"CON:0/20/640/100/Sushi CTRL-File CTRL-Empty/AUTO/CLOSE/WAIT" NOPROMPT
  224.  
  225.  
  226. Debugging printf's: kprintf and dprintf
  227. =======================================
  228. When using serial (or parallel) debugging and stress-testing tools,
  229. it is very useful to have your own program's debugging statements
  230. (such as "About to do xxx") mixed in with any potential hits
  231. from the debugging tools.
  232. In addition, it is very useful to have a printf-like command that
  233. can be used from within even the low level task or interrupt code.
  234. A clean way to add conditional debugging statements to a C program
  235. is to use a MACRO such a D(bug)) by including lines like the following
  236. in your program.  Set MYDEBUG to 1 to turn on debugging.
  237. Set bug to printf for printf debugging, or to kprintf (and link with
  238. debug.lib) for serial debugging, or to dprintf (and link with ddebug.lib)
  239. for parallel debugging.  The D(bug()) macro is neater in your code
  240. because it can be indented and you need not surround it with any
  241. #ifdef directives yourself.  Just be careful to remember to put two
  242. close paren's at the end of each D(bug()) statement, before the semicolon.
  243.  
  244. /**********    debug macros     ***********/
  245. #define MYDEBUG  1
  246. void kprintf(UBYTE *fmt,...);
  247. void dprintf(UBYTE *fmt,...);
  248. #define DEBTIME 0
  249. #define bug printf
  250. #if MYDEBUG
  251. #define D(x) (x); if(DEBTIME>0) Delay(DEBTIME);
  252. #else
  253. #define D(x) ;
  254. #endif /* MYDEBUG */
  255. /********** end of debug macros **********/
  256.  
  257. Example macro usage:
  258.     win = OpenWindow(&mynewwin);
  259.     D(bug("Opened window at $%lx\n", win));
  260.  
  261. Note that kprintf and dprintf debugging can be used inside even
  262. the lowest level task or interrupt code (although you better
  263. keep output down to a minimum during interrupts!).  The DEBTIME
  264. (Delay) in the macro above must be 0 however if you are doing
  265. output from anything other than a Process.
  266.  
  267.  
  268. Finding the Cause of Enforcer and Mungwall Hits
  269. ===============================================
  270. By using Enforcer and Mungwall while you are developing your software,
  271. you can catch problems as soon as they are introduced and greatly
  272. cut down your debugging time.  It is especially useful to place
  273. conditional remote debugging statements in your code as you write
  274. each routine so that they can easily be turned on when a problem occurs.
  275. You will easily be able to pinpoint the problem area when the kprintf
  276. (or dprintf) output is intermixed with the Enforcer or Mungwall output.
  277. The remote debugging commands kprintf and dprintf are avaiable in
  278. the linker libraries debug.lib (serial) and ddebug.lib (parallel)
  279. respectively.  These linker libs are supplied with some compilers
  280. and are also available on Commodore's Native Developer Update disks.
  281.  
  282. Some people prefer to use a source-level or single-stepping debugger
  283. in combination with Enforcer and Mungwall when tracking down a
  284. problem to single-step through their code until the hit occurs.
  285. A different low-level method of locating Enforcer or Mungwall hits is to
  286. disassemble program memory where the hit occurred.  If the hit occurred
  287. in ROM, first try using OWNER to determine ROM subsystem of that address.
  288. For example, OWNER 0x202442 might return the following on a soft-kicked
  289. A2500:
  290.  
  291. Address  - Owner
  292. --------   -----
  293. 00202442 - in resident module: exec 39.47 (28.8.92)
  294.  
  295.  
  296. Then use LVO to determine the probable function at that address within
  297. the subsystem:  LVO exec romaddress=0x202442
  298.  
  299. Closest to $202442 without going over:
  300. exec.library  LVO $fe0e -498  OpenResource() jumps to $202358 on this system
  301.  
  302. (See Owner and LVO section for more information on these tools)
  303.  
  304. If this does does not give enough clue, try disassembling just before
  305. other ROM and RAM addresses shown in the Enforcer stack dump line.
  306. If code is found, these may be application or ROM functions
  307. which called the routine that generated the hit.
  308.  
  309. If the hit occurs in RAM code, use various methods to match up the
  310. disassembly with your own code.  Assembly programmers can just compare
  311. the disassembly to their source.  Others may wish to take the hex values
  312. of a sequence of position-independent 68000 instructions near the hit
  313. (ie. no addresses except for offsets and branches) and do a search for
  314. this binary pattern in your object modules.  If you find the pattern,
  315. do a mixed source and object disassembly of that object module (for example,
  316. with SAS's OMD you could OMD >ram:dump mymodule.o mymodule.c) and then
  317. look in the output for instructions matching those where the hit occurred.
  318. NOte that when a hit occurs in a disk-loaded device or library, it is
  319. currently not possible to determine who owns the code where the hit occurred.
  320. This is because it is up to the device or library to store its
  321. seglist wherever it sees fit in its own library or device base.
  322. If you suspect that your hit is occuring in a disk-loaded library
  323. or device, you can try searching suspected disk libraries or devices
  324. for a match of the hex pattern of position-independent code near the hit.
  325.  
  326.  
  327. Deciphering Enforcer and Mungwall Output
  328. ========================================
  329. Enforcer and Mungwall provide lots of valuable information to help
  330. debug your hits.
  331.  
  332.  
  333. SAMPLE ENFORCER OUTPUT:
  334.  
  335. Here is a sample Enforcer hit caused by a program called "lawbreaker".
  336.  
  337. WORD-READ from 00000014                        PC: 075899A6
  338. USP:  075A8BE0 SR: 0015 SW: 0769  (U0)(F)(D)  TCB: 075AE468
  339. Data: DDDD0041 DDDD1100 DDDD2200 DDDD3300 DDDD4400 DDDD5500 DDDD6600 DDDD7700
  340. Addr: AAAA0000 AAAA1100 AAAA2200 AAAA3300 AAAA4400 AAAA5500 07400810 --------
  341. Stck: 00000009 00000008 00000007 00000006 00000005 00000004 00000003 00000002
  342. Stck: 00000001 00F92A18 00001000 075AEE4C BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB
  343. Name: "Shell Process"  CLI: "lawbreaker"  Hunk 0000 Offset 00000096
  344.  
  345. LONG-WRITE to  FEEDFACE        data=DDDD0041   PC: 075899B8
  346. USP:  075A8BE0 SR: 0018 SW: 0709  (U0)(F)(-)  TCB: 075AE468
  347. Data: DDDD0041 DDDD1100 DDDD2200 DDDD3300 DDDD4400 DDDD5500 DDDD6600 DDDD7700
  348. Addr: AAAA0000 AAAA1100 AAAA2200 AAAA3300 AAAA4400 AAAA5500 07400810 --------
  349. Stck: 00000009 00000008 00000007 00000006 00000005 00000004 00000003 00000002
  350. Stck: 00000001 00F92A18 00001000 075AEE4C BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB
  351. Name: "Shell Process"  CLI: "lawbreaker"  Hunk 0000 Offset 000000A8
  352.  
  353.  
  354. Here is an explanation of the some of the important information:
  355.  
  356. PC:
  357.  
  358. Program Counter.  This is the address in memory where the program was
  359. executing instructions when the hit occured.
  360. For some kinds of hits this will often be the address of the instruction
  361. after the hit.  Note that if your program passes a bad pointer
  362. or an improperly initialized structure to a system ROM routine,
  363. you may cause ROM code to read or write to an illegal address.
  364.  
  365.  
  366. TYPE-SIZE from or to (e.g. WORD-READ from 00000014):
  367.  
  368. This is the type of illegal access and the address where it occurred.
  369. In the first example, the illegal access occurred at address $14, and
  370. is specified as a WORD-READ access.
  371. This means the illegal memory access was an attempt to read a word (2 bytes)
  372. at address $14.  Low memory accesses are often caused by NULL
  373. pointers to structures.  If, for example, your code or a ROM routine
  374. references a structure member at offset $14,
  375. and what you provided or used a NULL structure pointer, Enforcer will
  376. pick up a hit at address $14.  Other illegal READ accesses are
  377. BYTE-READ (generally caused by a bad string pointer), and LONG-READ
  378. (generally caused by a bad pointer or a bad pointer within a structure).
  379. An Enforcer hit will ocuur whenever a program attempts to read low memory
  380. addresses (generally caused by a NULL pointer of some type) or non-existent
  381. memory addresses (generally caused by an uninitialized pointer).
  382. When Enforcer catches an illegal READ access, it reports the access
  383. and prevents the program from reading the address by returning data
  384. of zero.
  385.  
  386. On illegal WRITE accesses (i.e. attempts to write to ROM, low memory,
  387. or non-existent memory) Enforcer will report BYTE-WRITE, WORD-WRITE,
  388. or LONG-WRITE hits (such as in the second example).  These mean the access
  389. would have illegally and dangerously written to memory which should not
  390. be written to, quite possibly causing memory to be trashed.
  391. WRITE hits can be caused by bad pointers or bad code.
  392. Fortunately, Enforcer prevents the actual memory trashing
  393. from occurring, and instead just reports it.  This can allow debugging
  394. severe low memory trashing problems which would normally crash your
  395. machine.  In the second example above, the CLI program "lawbreaker"
  396. tried to write the long value $DDDD0041 to the address $FEEDFACE.
  397.  
  398. Occasionally you will see an INSTRUCTION access of illegal
  399. memory meaning the PC (Program Counter) is at an address it has no
  400. legal reason to be at.  Generally this is caused by trashed code, a trashed
  401. return address on your stack, or an invalid library base.
  402. Hint - when an INSTRUCTION Enforcer hit occurs at a negative address,
  403. it is most often caused by a JSR to an LVO (negative word offset)
  404. from a NULL library base.  Check the Stack dump lines for a possible
  405. return address to the code that made the bad library call.
  406.  
  407.  
  408. "data=xxxxxxxx":
  409.  
  410. On WRITE hits, Enforcer will show you the data that would have been
  411. written to the illegal address.
  412.  
  413.  
  414. Register Dump Lines:
  415.  
  416. All of the middle Enforcer lines show the contents of the program's
  417. registers and stack at the time of the hit.  The Data: line shows
  418. the D registers (D0 though D7).  The Addr: line shows the A registers
  419. (A0 though A6).  A7 (the Stack register) is shown as USP, and the contents
  420. of the top of the stack is shown in the Stck: lines (note - more Stck:
  421. lines are available via a command line option of the new Enforcer).
  422. The USP line also contains the contains of additional processor status
  423. registers, and also the address of the Task Control Block (TCB).
  424. On the same line are symbols which specify whether a Forbid (F) and/or
  425. a Disable (D) was in effect when the hit occurred.
  426.  
  427.  
  428. Name and Hunk Offset:
  429.  
  430. Example:
  431. Name: "Shell Process"  CLI: "lawbreaker"  Hunk 0000 Offset 000000A8
  432.  
  433. This line shows the task name,  and CLI command name (if any)
  434. of the task or command that was executing when the hit occurred.
  435. If possible, Enforcer also provides a hunk offset to where the program
  436. counter was if the hit occured within the program's own code instructions.
  437.  
  438.  
  439.  
  440. SAMPLE MUNGWALL OUTPUT
  441. ======================
  442.  
  443. Here are sample Mungwall hits by a program called "mungwalltest".
  444. Additional explanation has been added in parentheses below each hit.
  445. For reference, the arguments for memory functions are AllocMem(size,type)
  446. and FreeMem(address,size).  The A: and C: addresses are Mungwall's
  447. guess at the address from which AllocMem was called.  The A: address
  448. is the address if the caller was assembler code.  The C: address is the
  449. probable address if the caller was C code, assuming a standard stub.
  450. Since Mungwall is wedged into the memory allocation functions, it can
  451. only guess the caller's address based on what is pushed on the stack.
  452. The "task" address on the first line of a Mungwall hit is the task address
  453. of the caller.  Mungwall checks for incorrect allocations (such as 0 size)
  454. during AllocMem, and checks for incorrect deallocations or trashing
  455. around allocations during FreeMem.  If trashing or incorrect deallocation
  456. is detected, Mungwall will both report it and refuse to free the memory.
  457.  
  458. Note that Mungwall has special code to prevent
  459. trapping the partial (wrong size) deallocations that are performed
  460. by some version of layers.library.  If any other debugging tools are
  461. also wedged into AllocMem and FreeMem, Mungwall's A: and C: addresses
  462. may be thrown off by additional information pushed on the stack, and
  463. Mungwall will also be unable to screen out any partial layers deallocations
  464. (which will show up as hits on your task's context).
  465.  
  466.  
  467. AllocMem(0x0,10000) attempted by `mungwalltest' (task 0x3E08F0)
  468.   from A:0x3EBB12 C:0x3EF552 SP:0x4559FC
  469. (means mungwalltest tried to allocate 0 bytes of memory)
  470.  
  471.  
  472. FreeMem(0x0,16) attempted by `mungwalltest' (task 0x3E08F0)
  473.   from A:0x3EBB40 C:0x3EF598 SP:0x4559F4
  474. (mungwalltest tried to free memory it never got - i.e. at address 0)
  475.  
  476.  
  477. FreeMem(0x2FE7C0,0) attempted by `mungwalltest' (task 0x3E08F0)
  478.   from A:0x3EBB40 C:0x3EF5A8 SP:0x4559EC
  479. (mungwalltest tried to free 0 bytes of memory)
  480.  
  481.  
  482. Mis-aligned FreeMem(0x2FE7C4,16) attempted by `mungwalltest' (task 0x3E08F0)
  483.   from A:0x3EBB40 C:0x3EF5B6 SP:0x4559E4
  484. (mungwalltest tried to free memory at an incorrect address)
  485.  
  486.  
  487. Mismatched FreeMem size 14!
  488. Original allocation: 16 bytes from A:0x3EBB12 C:0x3EF574 Task 0x3E08F0
  489. Testing with original size.
  490. (mungwalltest tried to free a different size from what it allocated)
  491.  
  492.  
  493. 19 byte(s) before allocation at 0x2FE7C0, size 16 were hit!
  494. >$: BBBBBBBB BBBBBBBB BB536572 6765616E 74277320 50657070 65722000
  495. (memory before this allocation was trashed; trash shown at right)
  496.  
  497.  
  498. 8 byte(s) after allocation at 0x2FE7C0, size 16 were hit!
  499. >$: 75622042 616E6400 BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB 
  500. (memory after this allocation was trashed; trash shown at left)
  501.  
  502.  
  503.   FreeMem(0x2FE7C0,14) attempted by `mungwalltest' (task 0x3E08F0)
  504.   from A:0x3EBB40 C:0x3EF5F4 SP:0x4559D0
  505. (deallocation refused due to trashing explained in last two reports)
  506.  
  507.  
  508. Failed memory allocation!
  509. AllocMem(0x500000000,1) attempted by `flush' (task 0x3E08F0)
  510.   from A:0x453E96 C:0x1 SP:0x4820F4
  511. (SHOWFAIL option shows flush tried to allocate memory and failed)
  512.  
  513.  
  514. As you can see, Mungwall alone can catch a large variety
  515. of memory-related software problems.  But one the most important
  516. benefits of Mungwall is that by filling freed memory with nasty
  517. 32-bit values, it can force subtle memory misuse problems
  518. into the open, by often causing the misuses to access addresses that
  519. can be trapped on by Enforcer.
  520.  
  521. Enforcer and Mungwall are required tools for the development of
  522. bug-free Amiga software.  If you don't have an MMU, get one.
  523. The investment in an A3000, 68030 card, or 68020+MMU card
  524. will quickly pay for itself by cutting down on your development
  525. and allowing you to catch and find software problems with Enforcer.  
  526. Enforcer and Mungwall are not just for developers and QA departments.
  527. Anyone who uses or reviews inhouse software or software for
  528. purchase or contract can benefit your company by catching hidden
  529. software problems during normal usage and examination of the programs.
  530. Many people at Commodore and other companies run Enforcer and Mungwall
  531. all of the time.  Keep that in mind if you are trying to impress a
  532. company with your software!
  533.  
  534.  
  535. Other Debugging and Testing Tools
  536. =================================
  537.  
  538. The next three tools, Memoration and Scratch by Bill Hawes, and IO_Torture
  539. by Bryce Nesbitt are important QA tools for testing the robustness of all
  540. application failure code, for uncovering illegal register usage in
  541. assembler code, and for detecting unsafe use of device IO requests.
  542. Following notes on these three are notes on some of the additional
  543. debugging and stresstest tools provided by CATS.
  544.  
  545.  
  546. Memoration
  547. ==========
  548. Memoration by Bill Hawes is a tool to selectively limit the ability of a
  549. task or module to allocate memory, thereby simulating the effects of a
  550. low-memory condition.  It provides the unique ability to selectively
  551. cause each individual memory allocation of a program, whether direct
  552. or indirect, to fail, thereby allowing you to test the failure path
  553. and abort code at every point in your application code.
  554.  
  555. Memoration works by SetFunctioning the Exec AllocMem and/or AllocVec
  556. entries and then screening the requests.  If a request from a particular
  557. task or range of addresses is received, memoration returns a zero instead
  558. of passing it through to AllocMem.
  559.  
  560. When a task or module is denied a memory request, memoration sends a
  561. message to the serial port identifying the client task ID, the address it
  562. was called from, and the size of the denied request.  If the software can't
  563. handle being denied its memory request, this message will typically be
  564. followed by a series of enforcer reports telling of how the software went
  565. ahead and wrote to location 0.
  566.  
  567.  
  568. Command-Line Parameters.
  569. Memoration accepts command-line parameters to specify the module or task
  570. name and the range of memory sizes to disallow.  The argument template is
  571.  
  572. MODULE,TASK/K,CLI/K/N,OFF/S,MIN/K/N,MAX/K/N,AFTER/K/N,EVERY/K/N,ALLADDR/S,
  573. ALLOCVEC/S,CHIP/S,FAST/S,BACKTRACE/K/N
  574.  
  575. and the specifications can be changed at any time by reissuing the command.
  576.  
  577.  
  578. MODULE is the name of a ROMTag or library.  The resident modules are
  579. searched first, followed by a search of the system library list.  When an
  580. entry is found, the range of addresses encompassing its code is determined
  581. using several methods.  For ROMTags the range extends from the ROMTag
  582. itself to the next higher module, or to RT_ENDSKIP if no higher module
  583. exists.  For libraries a certain amount of voodoo is required, as the
  584. location of the library ROMtag isn't stored in the (public) library
  585. structure. In this case memoration examines the LVOs to determine the
  586. lowest and highest addresses, and then searches for a ROMtag in the range
  587. (low-$2000,high+$2000).  If a ROMTag is found, memoration uses the smaller
  588. of the ROMTag addresss and the lowest LVO address as the low limit, and the
  589. larger of the RT_ENDSKIP address and the highest LVO address as the high
  590. limit.
  591.  
  592. TASK specifies the name of a task to trap.  The task must exist at the time
  593. memoration is run, and for best results should persist for the course of
  594. testing.  If you're using WShell (as you should be) you can define a name
  595. for a particular shell instance by using ``newwsh name sucker''.
  596.  
  597. CLI specifies a shell number as the task to trap.
  598.  
  599. MIN specifies the minimum memory request to trap.  The default is 0.
  600.  
  601. MAX specifies the maximum allocation to trap.  The default is 2000000.
  602.  
  603. OFF turns off memory trapping.  The code patch is left intact, but won't
  604. trap any requests until enabled again.  AllocMem and AllocVec traps
  605. can be turned on and off separately.
  606.  
  607. ALLOCVEC sets the trap for the AllocVec() entry, instead of AllocMem().
  608. Both functions can be trapped independently.
  609.  
  610. AFTER specifies the number of allocations (within other specifications) to
  611. pass before beginning the trap.
  612.  
  613. EVERY traps every Nth allocation meeting the specifications.
  614.  
  615. ALLADDR sets the address range to all memory.
  616.  
  617. CHIP limits the trap to CHIP memory specifications.
  618.  
  619. FAST limits the trap to FAST memory specifications.
  620.  
  621. BACKTRACE specifies the number of longwords of stack backtrace desired.
  622.  
  623.  
  624. Examples:
  625.   memoration myprog after 15  ; after 15th allocation, deny myprog any memory
  626.   memoration dos.library  ; disable all DOS allocations
  627.   memoration task DF0 min 400 ; disable larger allocations by DF0:
  628.   memoration icon.library task Workbench every 3
  629.   memoration console.device min 40 backtrace 8
  630.  
  631. Example test session to test failure of every allocation an application makes:
  632.  
  633. Open two shells - one for memoration (here 1>) and one for myprog (here 2>).
  634. Alternately, you could start myprog from Workbench.
  635. Run Enforcer and Mungwall.
  636. Have serial or Sushi debugging set up.
  637.  
  638. 1> memoration myprog after 0
  639. 2> myprog    ; a failure occurs but hopefully no hits or crashes
  640. 1> memoration off
  641. (exit myprog if it made it up)
  642.  
  643. 1> memoration myprog after 1
  644. 2> myprog    ; a failure occurs but hopefully no hits or crashes
  645. 1> memoration off
  646. (exit myprog if it made it up)
  647.  
  648. 1> memoration myprog after 2
  649. 2> myprog    ; a failure occurs but hopefully no hits or crashes
  650. 1> memoration off
  651. (exit myprog if it made it up)
  652.  
  653. etc.  Note - until you get up to a higher "after" number, myprog will likely
  654. fail during the startup code it is linked with - i.e. before even
  655. reaching your main() entry point.  
  656.  
  657. Further Notes.
  658. Memoration uses a seglist-split for its code patch, and so shouldn't be made
  659. resident, at least not on the first execution.  Memoration was written by
  660. William S. Hawes.
  661.  
  662.  
  663. Scratch
  664. =======
  665. Scratch by Bill Hawes purposely trashes the scratch registers (D1, A0, A1)
  666. on exit from library functions of any "scratched" library.
  667. This will point out assembler callers that accidentally or
  668. purposely depend upon getting "useful" values from those registers.  
  669. It is extrememly important that ALL assembler applications be tested with
  670. Scratch.  Even minor changes to the OS can change the values that happen to
  671. be left over in registers on exit from a system library function.
  672. Assembler code that is accidentally reusing a scratch register
  673. (for example A1) after a system call, or code that is looking at the
  674. wrong register for a result has the potential to break badly with
  675. even a minor change to the OS.  Scratch can catch these problems before
  676. you ship.  To use Scratch, see the script "SCRATCHALL.SCRIPT" which
  677. properly excepts certain system functions from scratching.
  678.  
  679.  
  680. IO_Torture
  681. ==========
  682. IO_torture is a tool which can be used to check for improper use
  683. or reuse of device IO requests.
  684.  
  685. IO_torture should be part of the standard test suite for all products.
  686.  
  687. Exec device IO usage is tracked by IO_torture.  If an IORequest is reused
  688. while still active, IO_torture will print a warning message on the serial
  689. port (parallel for IO_torture.par).
  690.  
  691. The current plan of IO_torture includes:
  692.  
  693.         SendIO() - Check that message is free.  Check for ReplyPort.
  694.         Be sure request is not linked into a list.
  695.  
  696.         BeginIO() - Check that message is free.  Check for ReplyPort.
  697.         Be sure request is not linked into a list.
  698.  
  699.         OpenDevice() - Mark message as free.  If error, trash IO_DEVICE,
  700.         IO_UNIT and LN_TYPE.
  701.         Be sure request is not linked into a list.
  702.  
  703.         CloseDevice() - Check that message is free.  Trash IO_DEVICE,
  704.         IO_UNIT.
  705.  
  706.  
  707. IO_torture does not currently check for another common mistake:
  708. After virtually all uses of AbortIO(IORequest), there should be a
  709. call to WaitIO(IORequest).  AbortIO() asks the device to finish
  710. the I/O as soon as possible; this may or may not happen instantly.
  711. AbortIO() does not wait for or remove the replied message.
  712.  
  713. Note regarding NT_MESSAGE:  NT_MESSAGE would seem to be the correct node
  714. type for an IO request which is newly initialized.  However, part of
  715. how IO_torture works is that it makes sure in-use requests are marked as
  716. NT_MESSAGE, and would normally complain if such an NT_MESSAGE came
  717. through BeginIO or SendIO (as it would signify reuse before ReplyMsg).
  718. So that IO_torture will not complain about a freshly initialized
  719. MT_MESSAGE IO request, IO_torture also checks to see if the message
  720. has ever been linked into a list.  If it has not, IO_torture will
  721. let the NT_MESSAAHE marked request by without complaining.  This
  722. is necessary because the amiga.lib CreateExtIO and CreateStdIO
  723. historically set a newly created IO request node type to NT_MESSAGE.
  724.  
  725.  
  726. Devmon
  727. ======
  728. Devmon is a tool which allows you to monitor the activity of any
  729. exec device.  It is extremely useful for debugging both application
  730. use of a device and your own device drivers.  Devmon captures
  731. (or outputs to serial or Sushi) debugging information everytime
  732. any vector of a monitored device is entered.  Optionally, Devmon
  733. can also report on the entry to (and in some cases, exit from)
  734. the exec library functions which call the device.
  735.  
  736. USAGE: devmon name.device unitnum [remote] [hex] [allunits] [full]
  737.  
  738. remote        means serial debugging output
  739. hex        means show values in hex
  740. allunits    monitor regardless of unit pointer (required if device
  741.             gives a new unit pointer to every opener)
  742. full        means also monitor exec device-related library functions
  743.  
  744.  
  745. Some sample Devmon output as generated by:
  746.  
  747.     devmon clipboard.device 0 allunits hex full remote
  748.  
  749.  
  750. In the following regular devmon output lines, UPPERCASE: signifies
  751. entry to an actual device vector, while MixedCase: signifies entry to
  752. (or Rts from) an exec function.  The number preceded by "@" is the
  753. address of the IO request.  The single letters following are
  754. abbreviations for the fields of an IOStdRequest (C means io_Command,
  755. F means io_Flags, E means io_Error, etc.).  When Devmon is exited,
  756. it outputs a key to these fields.
  757.  
  758. Here we see C:ConClip executing DoIO of a request containing CMD_WRITE
  759. (C = 3, as defined in exec/io.h) of 8 bytes (L=$8) of data at $30BDF0.
  760. We see the same IO request make it to the BEGINIO vector of the
  761. device, and then we see the DoIO completing successfully with an
  762. io_Actual (A=) of 8.
  763.  
  764. DoIO : @$478294 C= 3 F=$81 E=0 A=$4 L=$8 D=$30BDF0 O=$0 (C:ConClip)
  765. BEGIN: @$478294 C= 3 F=$1 E=0 A=$4 L=$8 D=$30BDF0 O=$0 (C:ConClip)
  766. DoRts: @$478294 C= 3 F=$81 E=0 A=$8 L=$8 D=$30BDF0 O=$8 (C:ConClip)
  767.  
  768.  
  769. TNT
  770. ===
  771. TNT installs a trap handler that replaces Software Error requesters
  772. with a large requester containing informative debugging information.
  773. TNT can be called in your user-startup (it does not need to be run).
  774. But it does not get along well with trap-based single-stepping debuggers.
  775. So if you plan to run a debugger, turn off TNT with TNT OFF.
  776.  
  777. TNT requesters contain PC, task/command name, SP, SSP, register, and
  778. stack contents information similar to that displayed by Enforcer.
  779.  
  780.  
  781. Owner and LVO
  782. =============
  783. Owner and LVO are very useful for determining the owner of a memory address.
  784. This can help you determine the location and even the cause of an
  785. Enforcer or Mungwall hit.
  786.  
  787. LVO requires the Amiga FD files for your OS version in a directory
  788. assigned the logical name FD:.  The FD files are provided with 
  789. the includes and linker libs for the OS.
  790.  
  791. When you get a hit, use OWNER to determine if the address is in a ROM
  792. module (such as exec or intuition), or in the loaded code, stack, port,
  793. or other memory owned by a program.  Note that owner can not determine
  794. if an address is in the code of a disk-loaded device or library because
  795. there is no standard place for devcies and libraries to store their
  796. seglist.
  797.  
  798. Example:
  799.  
  800. 1> owner 0x202443
  801.  
  802. Address  - Owner
  803. --------   -----
  804. 00202442 - in resident module: exec 39.47 (28.8.92)
  805.  
  806.  
  807. Now use LVO to determine the probable function at that address within
  808. the subsystem:
  809.  
  810. 1> LVO exec romaddress=0x202442
  811.  
  812. Closest to $202442 without going over:
  813. exec.library  LVO $fe0e -498  OpenResource() jumps to $202358 on this system
  814.  
  815. LVO can also be used as a programming helper to list one function and
  816. its FD comment:
  817.  
  818. 1> LVO exec AllocMem
  819. exec.library  LVO $ff3a -198  AllocMem()
  820. AllocMem(byteSize,requirements)(d0/d1)
  821.  
  822. LVO will list all of a library's LVOs if no function name is provided.
  823. With the optional CONTAINS keyword, LVO will also list the addresses
  824. each function jumps to on YOUR system (different on different systems).
  825. Note that if you have debugging tools installed which use SetFunction
  826. (for example, Mungwall, Devmon, or Scratch), LVO will not be able to
  827. determine the ROM address of the SetFunctioned library functions
  828. because the LVOs of those functions will point to the SetFunctioned
  829. RAM code.
  830.  
  831. LVO can also create command lines for the "Wedge" program.
  832.  
  833. Note that LVO and Wedge can only interact with actual
  834. library functions, not for their various stub interfaces which
  835. only exist in linker libraries.  Actual library functions are the
  836. functions listed in the FD file for the libraries.
  837. Note also that under new versions of the OS, some older library
  838. functions become unused by the OS and newer functions are used
  839. in their place.
  840.  
  841.  
  842. Wedge
  843. =====
  844. Wedge is a tool for wedging into almost any system library function
  845. and monitoring calls to and results from the function, for any or
  846. all system tasks.  Sometimes it can be more efficient to quickly
  847. wedge and monitor a system function rather than ad debugging code
  848. and recompile.  It used to be very difficult to create command
  849. line arguments for wedge.  But LVO can generate a template command
  850. line to "wedge" into any system function.
  851.  
  852. Example: Creates a wedge command for wedging into OpenScreen
  853.  
  854. 1> LVO intuition CloseScreen wedgeline      
  855. run wedge intuition 0xffbe 0x8100 0x8100 opt r   "c=CloseScreen(screen)(a0)"
  856.  
  857. If you execute the WEDGE command line above, you will receive serial
  858. reports on every call to CloseScreen.  To turn off the wedge, type
  859. WEDGE KILLALL.  See Wedge.doc for more information.
  860.  
  861.  
  862. Tstat
  863. =====
  864. Tstat is a handy little tool for checking the signals, priority,
  865. state, and other Task control block variables of any task or command.
  866. Tstat also does its best to show the task registers as they were
  867. saved at task-switch time, and the stack usage of the task or command.
  868. Note however that Tstat is looking at provate exec Task context information
  869. and therefore often needs to be updated for each OS release, and may
  870. misinterpret the task context data in unusual conditions such as
  871. a task switch which occures in the middle of an FPU instruction. 
  872. But it is very useful when checking for lost signals, bad Forbid or
  873. Disable counts, and hung Waits.  Tstat can monitor once, or periodically.
  874. For example, tstat MyProg -4 would monitor MyProg every 4/50's of a second
  875. until CTRL-C is hit.  In a pinch, Tstat can be used as a poor-man's
  876. logic state analyzer to track another program stuck in a loop.
  877.  
  878.  
  879. Other Memory Tools
  880. ==================
  881. EatMem is an interactive tool for scaling back the apparent amount of memory
  882. available to the system.  It is useful for testing applications in a simulated
  883. low-memory situation, as well as for testing how an application deals with
  884. only chip memory or only fast memory.  EatMem requires at least V37 OS.
  885.  
  886. MemList displays all memory blocks (both free and in-use) in the system.
  887. It can be useful for debugging fragmentation/deallocation problems.
  888. See also the NAMETAG option of Mungwall, and Munglist.
  889.  
  890. Frags displays a chart of current systen memory fragmentation.
  891.  
  892. Memmon saves current free memory and a comment to a file on demand.
  893. It is useful for documenting memory usage while testing various
  894. program operations.
  895.  
  896. Flush does two large allocations designed to fail and thereby cause
  897. all disk-loaded devices, libraries, and fonts which are not currently
  898. in use to be flushed from the system.  Useful when doing memory-loss
  899. testing and device or library development.
  900.  
  901. Snoop can be used to snoop memory allocations, but has largely been
  902. replaced by the more flexible Mungwall SNOOP option.  SnoopStrip
  903. is used to discard allocation/deallocation pairs from captured Snoop
  904. or Mungwall SNOOP output.
  905.  
  906.  
  907. Report
  908. ======
  909. All bug reports, compatibility problem reports, and enhancement
  910. requests must be generated with the latest Amiga "Report" program
  911. (currently version 39.5), or must be compatible with the output
  912. of the Amiga Report program.  This makes automatic submission
  913. and routing of bug reports possible.  The Report program is
  914. included on most developer tool and Devcon disks.  Report HELP
  915. will output instructions and submissions addresses.
  916.  
  917. We STRONGLY REQUEST that you submit your reports electronically
  918. if possible.  PLEASE USE REPORT.  Only mail them on paper if you
  919. have no other method available.  
  920.  
  921. European ADSP users: Post in appropriate closed adsp bugs topic
  922.  
  923. BIX/CIX: Post bugs in the appropriate bugs topic of your closed conference.
  924.  
  925. UUCP: to uunet!cbmvax!bugs OR rutgers!cbmvax!bugs OR bugs@commodore.COM
  926.   (enhancement requests to cbmvax!suggestions instead of cbmvax!bugs)
  927.  
  928. Mail: Mail individual bug reports in Report format, on disk if possible.
  929.   European developers: Mail bug reports to your support manager
  930.   unless your support manager says to mail directly to West Chester.
  931.   U.S./others mail to: Amiga Software Engineering, ATTN: BUG REPORTS,
  932.   CBM, 1200 Wilson Drive, West Chester, PA., 19380, USA
  933.  
  934. Please make sure the initial one-line bug description you provide
  935. in each of your reports is as explicit as possible.  Engineering's bug
  936. summary reports and bug processing tools often list only the one-line
  937. description for each bug.  "Bug in intuition" is a useless title
  938. for an intuition subsystem bug.  "Pixel trash when window dragged left"
  939. is a much better title.
  940.  
  941. The latest Report program always includes a list of the currently
  942. acceptable subsystems for bug reports and enhancement requests.
  943. These allow reports to be properly routed.  The current list is:
  944.  
  945. A2024           amigavision     cia.resource   filesysres     input.device   
  946. A2065           appshell        clipboard      filesystem     installer      
  947. A2090.A2090A    arexx           commodities    fonts          intuition      
  948. A2091.A590      art             con-handler    fountain       iprefs         
  949. A2232           as225           console.device gadget.classes keyboard       
  950. A2300           asl.library     creditcard     gadtools       keymap         
  951. A2410           audio.device    crossdos       gameport       keymaps        
  952. A2620           autoconfig      custom.chips   genlock        kickmenu       
  953. A2630           battclock       datatypes      graphics       layers         
  954. A3000           battmem         debug.lib      hardware       locale.library 
  955. AmigaBasic      bootmenu        disk.resource  hdbackup       mathffp        
  956. aa.chips        bridgeboard     diskfont       hdtoolbox      mathieee       
  957. alink           bru             documentation  icon.library   mathieeedoub   
  958. amiga.lib       bullet          dos.library    iconedit       mathieeesing   
  959. amigaguide      cdos.command    exec           ide.device     microemacs     
  960. amigaterm       cdtv            expansion      iffparse       monitors
  961. multiview       printer.driver  scsi.device    timer.device   util.command   
  962. narrator.device queue-handler   serial.device  toolkit        utility.library
  963. new.look        ram-handler     setpatch       toolmaker      wack           
  964. parallel.device ramdrive.device shell          tools          wbtag          
  965. port-handler    ramlib          speak-handler  trackdisk      workbench      
  966. potgo.resource  resource        startup        translations                  
  967. preferences     sana2           strap          translator                    
  968. printer.device  script          system.command unix
  969.